﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Felbot.Interaction;
using Felbot.Interface;
using Felbot.Profiles;

namespace Felbot {
    /// <summary>
    /// This is the main form which Felbot starts from. Most other forms are accessible from here.
    /// </summary>
    public partial class frmMain : Form {
        #region Fields and Properties
        private frmProfileConfiguration m_frmProfileConfig;
        private frmGlobalConfiguration m_frmGlobalConfig;
        private frmUserEntryManager m_frmUserEntryManager;
        private frmCommandManager m_frmCommandManager;
        private frmFlagsManager m_frmFlagsManager;
        private frmCDKeyManager m_frmCDKeyManager;
        private frmOpenProfile m_frmOpenProfile;
        private frmScriptOutput m_frmScriptOutput;
        private frmLogViewer m_frmLogViewer;
        private bool m_ShowPackets = false;
        private int m_WindowStyle = 0;

        private int m_LastPositionL = 0;
        private int m_LastPositionT = 0;
        private int m_LastPositionW = 0;
        private int m_LastPositionH = 0;
        private FormWindowState m_LastState = FormWindowState.Normal;

        private List<string> m_CommandArgs = new List<string>();

        /// <summary>
        /// Gets the instance ShowPackets setting.
        /// </summary>
        public bool ShowPackets {
            get {
                return m_ShowPackets;
            }
        }

        /// <summary>
        /// Gets the window style setting (at start up). It cannot be changed without a restart of the bot.
        /// </summary>
        public int WindowStyle {
            get {
                return m_WindowStyle;
            }
        }

        /// <summary>
        /// Gets the script output form.
        /// </summary>
        public frmScriptOutput ScriptOutput {
            get {
                return m_frmScriptOutput;
            }
        }
        #endregion

        #region Load and Close
        /// <summary>
        /// Creates a new main form.
        /// </summary>
        /// <param name="args">The program arguments.</param>
        public frmMain(string[] args) {
            InitializeComponent();

            StoreCommandLine(args);

            #region Init
            CommandControl.Initialize();
            UserEntryControl.Initialize();
            ProfileControl.Initialize();
            #endregion

            #region Start-Up Settings
            #region PositionChoice
            switch (ProfileControl.Global.GetSetting("StartUp", "PositionChoice").ToInteger(0)) {
                case 0:
                default: //default
                    this.StartPosition = FormStartPosition.WindowsDefaultBounds;
                    break;
                case 1: //store
                case 2: //custom
                    this.Location = new Point(
                        ProfileControl.Global.GetSetting("StartUp", "PositionL").ToInteger(200),
                        ProfileControl.Global.GetSetting("StartUp", "PositionT").ToInteger(200));
                    this.Size = new Size(
                        ProfileControl.Global.GetSetting("StartUp", "PositionW").ToInteger(800),
                        ProfileControl.Global.GetSetting("StartUp", "PositionH").ToInteger(600));
                    this.StartPosition = FormStartPosition.Manual;
                    break;
            }
            m_LastPositionL = this.Left;
            m_LastPositionT = this.Top;
            m_LastPositionW = this.Width;
            m_LastPositionH = this.Height;
            #endregion
            #region StateChoice
            switch (ProfileControl.Global.GetSetting("StartUp", "State").ToInteger(0)) {
                case 4: //In Tray
                case 0:
                default: //Default
                    break;
                case 1: //Normal
                    this.WindowState = FormWindowState.Normal;
                    break;
                case 2: //Maximized
                    this.WindowState = FormWindowState.Maximized;
                    break;
                case 3: //Minimized
                    this.WindowState = FormWindowState.Minimized;
                    break;
            }
            m_LastState = this.WindowState;
            #endregion
            #region StyleChoice
            m_WindowStyle = ProfileControl.Global.GetSetting("StartUp", "StyleChoice").ToInteger(0);
            switch (WindowStyle) {
                case 0:
                default: //mdi parent
                    tabs.Visible = false;
                    break;
                case 1: //tabbed
                    break;
                case 2: //separate
                    tabs.Visible = false;
                    IsMdiContainer = false;
                    break;
            }
            #endregion
            #endregion
        }

        private void frmMain_Load(object sender, EventArgs e) {
            if (ProfileControl.Global.GetSetting("StartUp", "State").ToInteger(0) == 4) //tray
                HideInTray();
            this.Text = "Felbot " + Properties.Resources.Version + " by Joe[x86] and Ribose";
            lblStatus.Text = "Ready";
            m_frmScriptOutput = Show<frmScriptOutput>(m_frmScriptOutput);
            m_frmScriptOutput.Hide();
            ProcessCommandLine();
            ProfileControl.LoadOnFelbotStart(this);
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e) {
            m_frmScriptOutput.Terminate();
        }
        #endregion

        #region Command Line
        public void StoreCommandLine(string[] args) {
            foreach (string arg in args) {
                m_CommandArgs.Add(arg);
            }
        }

        public void ProcessCommandLine() {
            List<string> filePathFrags = new List<string>();
            bool isFindingFilePath = false;
            foreach (string arg in m_CommandArgs) {
                switch (arg.ToLower()) {
                    case "-showpackets":
                        m_ShowPackets = true;
                        mnuToolsPackets.Checked = true;
                        break;

                    default:
                        string filepath = "";
                        if (arg.StartsWith("\"") && !isFindingFilePath) {
                            isFindingFilePath = true;
                        }

                        if (isFindingFilePath) {
                            if (arg.EndsWith("\"")) {
                                filePathFrags.Add(arg);
                                isFindingFilePath = false;
                                foreach (string filepathpart in filePathFrags)
                                    filepath += filepathpart + " ";
                                filepath.Trim('"');
                            } else {
                                filePathFrags.Add(arg);
                                continue;
                            }
                        } else {
                            filepath = arg;
                        }

                        FileInfo info = new FileInfo(filepath);
                        if (info.Exists) {
                            switch (info.Extension) {
                                case ".fbp":
                                    ImportProfile(info);
                                    break;
                            }
                        }

                        break;
                }
            }
        }
        #endregion

        #region Profile Import and Export
        public void ImportProfile() {
            dlgExportProfile.Title = "Import a Profile";
            dlgImportProfile.ShowDialog(m_frmProfileConfig);
        }

        private void dlgImportProfile_FileOk(object sender, CancelEventArgs e) {
            foreach (string file in dlgImportProfile.FileNames) {
                ImportProfile(new FileInfo(file));
            }
        }

        private void ImportProfile(FileInfo file) {
            if (!file.Exists) {
                MessageBox.Show("The profile " + file.Name + " does not exist.",
                                "Felbot",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                return;
            }

            if (file.Directory != new DirectoryInfo(Program.ApplicationFolder)) {
                string newLocation = Program.ApplicationFolder + "\\" + file.Name;
                if (File.Exists(newLocation)) {
                    if (MessageBox.Show("The profile " + file.Name + " already exists.  " +
                                        "Do you want to overwrite it?",
                                        "Felbot",
                                        MessageBoxButtons.YesNo,
                                        MessageBoxIcon.Exclamation,
                                        MessageBoxDefaultButton.Button2)
                        == DialogResult.Yes) {
                        file.CopyTo(newLocation, true);
                    }
                } else {
                    file.CopyTo(newLocation, false);
                }
            }

            Profile newProfile = ProfileControl.MakeProfile(file.Name.Substring(0, file.Name.Length - file.Extension.Length));

            if (MessageBox.Show("The profile " + newProfile.ProfileName + " was successfully imported.  " +
                                "Do you want to open it?",
                                "Felbot",
                                MessageBoxButtons.YesNo,
                                MessageBoxIcon.Question,
                                MessageBoxDefaultButton.Button1)
                == DialogResult.Yes) {
                OpenProfile(newProfile.ProfileName);
            }
        }

        public void ExportProfile(Profile profile) {
            dlgExportProfile.FileName = profile.ProfileName + ".fbp";
            dlgExportProfile.Tag = (object) profile;
            dlgExportProfile.Title = "Export Profile " + profile.ProfileName;
            dlgExportProfile.ShowDialog(m_frmProfileConfig);
        }

        private void dlgExportProfile_FileOk(object sender, System.ComponentModel.CancelEventArgs e) {
            ExportProfile((Profile) dlgExportProfile.Tag, new FileInfo(dlgExportProfile.FileName));
        }

        private void ExportProfile(Profile profile, FileInfo exportLocation) {
            profile.SaveSettings();
            FileInfo file = new FileInfo(profile.IniParser.Path);

            if (!file.Exists) {
                MessageBox.Show("The profile file for " + profile.ProfileName + " does not exist.",
                                "Felbot",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                return;
            }

            if (exportLocation.Exists) {
                if (MessageBox.Show("The file " + exportLocation.Name + " already exists.  " +
                                    "Do you want to overwrite it?",
                                    "Felbot",
                                    MessageBoxButtons.YesNo,
                                    MessageBoxIcon.Exclamation,
                                    MessageBoxDefaultButton.Button2)
                    == DialogResult.Yes) {
                    file.CopyTo(exportLocation.FullName, true);
                }
            } else {
                file.CopyTo(exportLocation.FullName, false);
            }

            MessageBox.Show("The profile " + profile.ProfileName + " was successfully " +
                            "exported to " + exportLocation.Name + ".",
                            "Felbot",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
        }
        #endregion

        #region Menus
        #region Menu File
        private void mnuProfileNew_Click(object sender, EventArgs e) {
            m_frmProfileConfig = Show<frmProfileConfiguration>(m_frmProfileConfig);
            m_frmProfileConfig.NewProfile();
        }

        private void mnuProfileOpen_Click(object sender, EventArgs e) {
            m_frmOpenProfile = Show<frmOpenProfile>(m_frmOpenProfile);
        }

        private void mnuProfileClose_Click(object sender, EventArgs e) {
            foreach (Form m_frmProfile in MdiChildren) {
                if (m_frmProfile.GetType().Equals(typeof(frmProfile)) && m_frmProfile.Focused) {
                    m_frmProfile.Close();
                    break;
                }
            }
        }

        private void mnuGlobalManage_Click(object sender, EventArgs e) {
            m_frmGlobalConfig = Show<frmGlobalConfiguration>(m_frmGlobalConfig);
        }

        private void mnuProfileManage_Click(object sender, EventArgs e) {
            m_frmProfileConfig = Show<frmProfileConfiguration>(m_frmProfileConfig);
        }

        private void mnuUsersManage_Click(object sender, EventArgs e) {
            m_frmUserEntryManager = Show<frmUserEntryManager>(m_frmUserEntryManager);
        }

        private void mnuCmdsManage_Click(object sender, EventArgs e) {
            m_frmCommandManager = Show<frmCommandManager>(m_frmCommandManager);
        }

        private void mnuFlagsManage_Click(object sender, EventArgs e) {
            m_frmFlagsManager = Show<frmFlagsManager>(m_frmFlagsManager);
        }

        private void mnuCDKeysManage_Click(object sender, EventArgs e) {
            m_frmCDKeyManager = Show<frmCDKeyManager>(m_frmCDKeyManager);
        }

        private void mnuViewLogs_Click(object sender, EventArgs e) {
            m_frmLogViewer = Show<frmLogViewer>(m_frmLogViewer);
        }

        private void mnuFileExit_Click(object sender, EventArgs e) {
            this.Close();
        }
        #endregion

        #region Menu Scripts
        private void mnuScriptsOutput_Click(object sender, EventArgs e) {
            m_frmScriptOutput = Show<frmScriptOutput>(m_frmScriptOutput);
        }

        private void mnuScriptsReload_Click(object sender, EventArgs e) {
            m_frmScriptOutput.ReloadScripts();
        }
        #endregion

        #region Menu Tools
        private void mnuToolsMinimize_Click(object sender, EventArgs e) {
            HideInTray();
        }

        private void mnuToolsPackets_Click(object sender, EventArgs e) {
            m_ShowPackets = !m_ShowPackets;
            mnuToolsPackets.Checked = ShowPackets;
        }


        #region Menu Reload
        private void mnuToolsReloadCommands_Click(object sender, EventArgs e) {
            CommandControl.Reload();
        }

        private void mnuToolsReloadUsers_Click(object sender, EventArgs e) {
            UserEntryControl.Reload();
        }
        #endregion
        #endregion

        #region Menu Window
        private void mnuWindowCasc_Click(object sender, EventArgs e) {
            LayoutMdi(MdiLayout.Cascade);
        }

        private void mnuWindowTileV_Click(object sender, EventArgs e) {
            LayoutMdi(MdiLayout.TileVertical);
        }

        private void mnuWindowTileH_Click(object sender, EventArgs e) {
            LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void mnuWindowCloseAll_Click(object sender, EventArgs e) {
            foreach (Form childForm in MdiChildren) {
                childForm.Close();
            }
        }
        #endregion

        #region Menu Help
        private void mnuHelpDocs_Click(object sender, EventArgs e) {
            Process.Start(Environment.CurrentDirectory + "\\readme.txt");
        }

        private void mnuHelpOnline_Click(object sender, EventArgs e) {
            Process.Start("http://felbot.googlecode.com/");
        }

        private void mnuHelpAbout_Click(object sender, EventArgs e) {
            new frmAbout().ShowDialog();
        }
        #endregion

        #region Notify Icon
        private void notifyIcon_DoubleClick(object sender, EventArgs e) {
            RestoreFromTray();
        }

        #region ContextMenu
        private void mnuNotifyRestore_Click(object sender, EventArgs e) {
            RestoreFromTray();
        }
        #endregion

        private void HideInTray() {
            m_LastState = this.WindowState;
            m_LastPositionL = this.Left;
            m_LastPositionT = this.Top;
            m_LastPositionW = this.Width;
            m_LastPositionH = this.Height;
            notifyIcon.Visible = true;
            notifyIcon.Text = this.Text;
            this.Hide();
        }

        private void RestoreFromTray() {
            this.Location = new Point(m_LastPositionL, m_LastPositionT);
            this.Size = new Size(m_LastPositionW, m_LastPositionH);
            this.WindowState = m_LastState;
            notifyIcon.Visible = false;
            this.Show();
        }
        #endregion
        #endregion

        #region Global Profile Controls
        private T Show<T>(T frm) where T : Form, new() {
            if (frm == null || !frm.Created) {
                frm = new T();
                MakeChild(frm);
                frm.Show();
            } else {
                frm.Show();
                frm.Focus();
            }
            return frm;
        }

        private void MakeChild(Form frm) {
            switch (WindowStyle) {
                default:
                case 0: //children
                case 1: //tabs
                    if (frm.GetType() == typeof(frmProfile))
                        frm.MdiParent = this;
                    break;
                case 2: //separate
                    break;
            }
        }

        /// <summary>
        /// Opens a profile by the name given.
        /// </summary>
        /// <param name="a_sProfileName">The profile name.</param>
        public void OpenProfile(string profileName) {
            Profile profile = ProfileControl.GetProfile(profileName);
            profile.Open = true;
            frmProfile profileForm = new frmProfile(profile);
            switch (WindowStyle) {
                default:
                case 0: //children
                case 2: //separate
                    break;
                case 1: //tabs
                    profileForm.WindowState = FormWindowState.Maximized;
                    profileForm.MaximizeBox = false;
                    profileForm.MinimizeBox = false;
                    break;
            }
            MakeChild(profileForm);
            if (profileForm.Profile.GetSetting("General", "State").ToInteger(0) != 3)
                profileForm.Show();
            else
                HideProfile(profileForm);
            profileForm.Initialize();
        }

        /// <summary>
        /// Opens the configuration form for a profile by the name given.
        /// </summary>
        /// <param name="a_pProfile">The profile name.</param>
        public void EditProfile(Profile profile) {
            m_frmProfileConfig = Show<frmProfileConfiguration>(m_frmProfileConfig);
            m_frmProfileConfig.EditProfile(profile);
        }

        /// <summary>
        /// Call this to tell all profile forms that the FCS settings have changed, and the RTBs should be refreshed.
        /// </summary>
        public void RefreshRtbs() {
            foreach (Form form in MdiChildren)
                if (form.GetType().Equals(typeof(frmProfile)))
                    (form as frmProfile).RefreshRtb();
        }

        private delegate void EventDelegate(object sender, EventArgs e);

        /// <summary>
        /// Call this to hide a specified profile form and allow resurrection through the main form's menus.
        /// </summary>
        /// <param name="form">The form to hide.</param>
        public void HideProfile(frmProfile form) {
            if (form == null)
                return;

            mnuToolsUnhideEmpty.Visible = false;

            ToolStripMenuItem mnuToolsUnhideItem = new ToolStripMenuItem(form.Profile.ProfileName);
            mnuToolsUnhideItem.Click += new EventHandler((EventDelegate) delegate(object sender, EventArgs e) {
                mnuToolsUnhide.DropDownItems.Remove(mnuToolsUnhideItem);

                if (mnuToolsUnhide.DropDownItems.Count == 1)
                    mnuToolsUnhideEmpty.Visible = true;

                form.Show();

                form.RefreshRtb();
            });
            mnuToolsUnhide.DropDownItems.Add(mnuToolsUnhideItem);

            if (form.Visible)
                form.Hide();
        }
        #endregion

        #region Resize
        private void MDIMain_ResizeEnd(object sender, EventArgs e) {
            if (this.WindowState == FormWindowState.Normal) {
                if (ProfileControl.Global.GetSetting("StartUp", "PositionChoice").ToInteger(0) == 1) {
                    //store
                    ProfileControl.Global.SetSetting("StartUp", "PositionL", this.Left);
                    ProfileControl.Global.SetSetting("StartUp", "PositionT", this.Top);
                    ProfileControl.Global.SetSetting("StartUp", "PositionW", this.Width);
                    ProfileControl.Global.SetSetting("StartUp", "PositionH", this.Height);
                    ProfileControl.Global.SaveSettings();
                }
            }
        }
        #endregion
    }
}